From 71c0ba1f01b98770ec2c60cdb935ffb36c1830a9 Mon Sep 17 00:00:00 2001 From: joonhoekim <26rote@gmail.com> Date: Mon, 8 Dec 2025 12:08:00 +0900 Subject: (김준회) 테이블 커스텀 훅 버전 생성 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/[lng]/test/table-v3/page.tsx | 188 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 188 insertions(+) create mode 100644 app/[lng]/test/table-v3/page.tsx (limited to 'app/[lng]/test/table-v3/page.tsx') diff --git a/app/[lng]/test/table-v3/page.tsx b/app/[lng]/test/table-v3/page.tsx new file mode 100644 index 00000000..eccf7cff --- /dev/null +++ b/app/[lng]/test/table-v3/page.tsx @@ -0,0 +1,188 @@ +"use client"; + +import * as React from "react"; +import { useClientTable, ClientVirtualTable } from "@/components/client-table-v3"; +import { productColumns } from "../table-v2/columns"; +import { + getProductTableData, + getAllProducts, + getProductTableDataWithGrouping, + GroupInfo +} from "../table-v2/actions"; +import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; +import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; +import { Badge } from "@/components/ui/badge"; +import { ChevronDown, ChevronRight } from "lucide-react"; + +// --- Components for Examples --- + +function ClientSideExample() { + const [products, setProducts] = React.useState([]); + + // Load initial data once + React.useEffect(() => { + getAllProducts().then(setProducts); + }, []); + + // Hook handles table state + const { table, isLoading } = useClientTable({ + fetchMode: "client", + data: products, + columns: productColumns, + enablePagination: true, + enableGrouping: true, + }); + + return ( + + + Pattern 1: Client-Side (V3) + + Uses `useClientTable` hook for simplified state management. + + + + + + + ); +} + +function ServerFactoryExample() { + // Hook handles everything: state, fetching, debouncing + const { table, isLoading } = useClientTable({ + fetchMode: "server", + fetcher: getProductTableData, + columns: productColumns, + enablePagination: true, + enableUserPreset: true, // We can enable this in options too? No, hook doesn't care. Component cares. + }); + + return ( + + + Pattern 2: Factory Service (V3) + + Zero boilerplate state management in the component. + + + + + + + ); +} + +function ServerGroupingExample() { + // Adapter for V2 fetcher signature to work with V3 hook + // The V2 action expects (state, expandedGroups), but V3 hook passes (state). + // We wrap it to extract expandedGroups from state.expanded. + const fetcher = React.useCallback((state: any) => { + const expanded = state.expanded || {}; + // Convert TanStack ExpandedState { [key]: true } to string[] + const expandedKeys = Object.keys(expanded).filter(k => expanded[k]); + return getProductTableDataWithGrouping(state, expandedKeys); + }, []); + + // Pattern 2-B support + const { + table, + isLoading, + isServerGrouped, + serverGroups, + refresh, + } = useClientTable({ + fetchMode: "server", + fetcher, + columns: productColumns, + enablePagination: true, + enableGrouping: true, + }); + + // When serverGroups change (new grouping), reset expansion + // (In a real app, you might want to persist expansion logic in the fetcher wrapper or hook) + + return ( + + + Pattern 2-B: Server Grouping (V3) + + Hook manages state, Component manages Custom Rendering for Groups. + + + + {/* We need the toolbar even in grouped mode */} +
+

+ Group by a column (Category, Status, IsNew) to see server grouping. +

+
+ + {isServerGrouped ? ( +
+ {serverGroups.map((group: GroupInfo) => ( +
+
+ {String(group.groupValue)} + ({group.count}) +
+ {/* Rows would go here */} +
+ ))} +
+ ) : ( + + )} +
+
+ ); +} + +export default function TableV3Page() { + return ( +
+
+

ClientVirtualTable V3 DX Demo

+

+ Demonstrating the new `useClientTable` hook for improved Developer Experience. +

+
+ + + + Client-Side + Server Factory + Server Grouping + + + + + + + + + + + + + + +
+ ); +} + -- cgit v1.2.3